package builder

import (
	"xindl/deployer/pkg/errors"
)

// 构建工具类型
const (
	BuildToolMaven  = "maven"
	BuildToolGradle = "gradle"
)

// 默认配置
const (
	DefaultJDKVersion = "21"
	DefaultImageTag   = "latest"
)

// JDK版本常量
const (
	JDK8  = "8"
	JDK11 = "11"
	JDK17 = "17"
	JDK21 = "21"
)

// 构建器工厂实现
type DefaultBuilderFactory struct {
	debug bool
}

// 创建新的构建器工厂
func NewBuilderFactory(debug bool) BuilderFactory {
	return &DefaultBuilderFactory{
		debug: debug,
	}
}

// 创建构建器
func (f *DefaultBuilderFactory) CreateBuilder(buildTool string) (Builder, error) {
	// 验证构建工具类型
	if err := validateBuildTool(buildTool); err != nil {
		return nil, err
	}

	// 创建对应的构建器
	switch buildTool {
	case BuildToolMaven:
		return NewMavenBuilder(&BuildConfig{}, f.debug), nil
	case BuildToolGradle:
		return NewGradleBuilder(&BuildConfig{}, f.debug), nil
	default:
		return nil, errors.NewBuildError("不支持的构建工具类型").
			WithContext("buildTool", buildTool)
	}
}

// 验证构建工具类型
func validateBuildTool(buildTool string) error {
	switch buildTool {
	case BuildToolMaven, BuildToolGradle:
		return nil
	default:
		return errors.NewConfigError("无效的构建工具类型").
			WithContext("buildTool", buildTool).
			WithContext("supported", "maven, gradle")
	}
}

// 验证JDK版本
func validateJDKVersion(version string) error {
	switch version {
	case JDK8, JDK11, JDK17, JDK21:
		return nil
	default:
		return errors.NewConfigError("不支持的JDK版本").
			WithContext("version", version).
			WithContext("supported", "8, 11, 17, 21")
	}
}

// 创建构建配置
func NewBuildConfig(serviceName, buildTool string) *BuildConfig {
	return &BuildConfig{
		ServiceName: serviceName,
		BuildTool:   buildTool,
		JDKVersion:  DefaultJDKVersion,
		SkipTests:   true,
		ImageTag:    DefaultImageTag,
		Args:        make([]string, 0),
	}
}

// 验证构建配置
func ValidateConfig(config *BuildConfig) error {
	if config == nil {
		return errors.NewConfigError("构建配置不能为空")
	}

	// 验证基本信息
	if config.ServiceName == "" {
		return errors.NewConfigError("服务名称不能为空")
	}

	if config.WorkDir == "" {
		return errors.NewConfigError("工作目录不能为空")
	}

	if config.CacheDir == "" {
		return errors.NewConfigError("缓存目录不能为空")
	}

	// 验证构建工具
	if err := validateBuildTool(config.BuildTool); err != nil {
		return err
	}

	// 验证JDK版本
	if err := validateJDKVersion(config.JDKVersion); err != nil {
		return err
	}

	// 验证Docker配置
	if config.ImageName == "" {
		return errors.NewConfigError("镜像名称不能为空")
	}

	return nil
}

// 构建配置构建器
type BuildConfigBuilder struct {
	config *BuildConfig
}

// 创建新的构建配置构建器
func NewBuildConfigBuilder(serviceName, buildTool string) *BuildConfigBuilder {
	return &BuildConfigBuilder{
		config: NewBuildConfig(serviceName, buildTool),
	}
}

// 设置工作目录
func (b *BuildConfigBuilder) WithWorkDir(workDir string) *BuildConfigBuilder {
	b.config.WorkDir = workDir
	return b
}

// 设置缓存目录
func (b *BuildConfigBuilder) WithCacheDir(cacheDir string) *BuildConfigBuilder {
	b.config.CacheDir = cacheDir
	return b
}

// 设置JDK版本
func (b *BuildConfigBuilder) WithJDKVersion(version string) *BuildConfigBuilder {
	b.config.JDKVersion = version
	return b
}

// 设置是否跳过测试
func (b *BuildConfigBuilder) WithSkipTests(skip bool) *BuildConfigBuilder {
	b.config.SkipTests = skip
	return b
}

// 设置Profile
func (b *BuildConfigBuilder) WithProfile(profile string) *BuildConfigBuilder {
	b.config.Profile = profile
	return b
}

// 添加构建参数
func (b *BuildConfigBuilder) WithArgs(args ...string) *BuildConfigBuilder {
	b.config.Args = append(b.config.Args, args...)
	return b
}

// 设置Docker配置
func (b *BuildConfigBuilder) WithDockerConfig(mirror, imageName, imageTag string) *BuildConfigBuilder {
	b.config.DockerMirror = mirror
	b.config.ImageName = imageName
	b.config.ImageTag = imageTag
	return b
}

// 设置资源限制
func (b *BuildConfigBuilder) WithResourceLimits(cpuLimit, memoryLimit string) *BuildConfigBuilder {
	b.config.CPULimit = cpuLimit
	b.config.MemoryLimit = memoryLimit
	return b
}

// 构建配置
func (b *BuildConfigBuilder) Build() (*BuildConfig, error) {
	if err := ValidateConfig(b.config); err != nil {
		return nil, errors.WithContext(err, "service", b.config.ServiceName)
	}
	return b.config, nil
}
